<?php
declare(strict_types=1);

namespace Kiri\Router;

use Closure;
use Kiri;
use Kiri\Router\Format\IFormat;
use Kiri\Router\Format\MixedFormat;
use Kiri\Router\Format\NoBody;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class Handler implements RequestHandlerInterface
{

    /**
     * @var IFormat
     */
    protected mixed $format;


    /**
     * @var array
     */
    protected array $methods = [];


    /**
     * @param array|Closure $handler
     * @param array $parameters
     * @param string|null $parameter
     */
    public function __construct(public array|Closure $handler, public array $parameters, ?string $parameter)
    {
        if ($parameter !== null) {
            $this->format = Kiri::getDi()->get($parameter);
        } else {
            $this->format = Kiri::getDi()->get(MixedFormat::class);
        }
    }


    /**
     * @param string $method
     * @return void
     * @throws
     */
    public function setRequestMethod(string $method): void
    {
        if ($method == 'HEAD' || $method == 'OPTIONS') {
            $this->format = Kiri::getDi()->get(NoBody::class);
        }
    }


    /**
     * @return bool
     */
    public function isClosure(): bool
    {
        return $this->handler instanceof Closure;
    }


    /**
     * @param string $interface
     * @return bool
     */
    public function implement(string $interface): bool
    {
        if (!$this->handler instanceof Closure) {
            return $this->handler[0] instanceof $interface;
        }
        return false;
    }


    /**
     * @return string|null
     */
    public function getClass(): ?string
    {
        if ($this->handler instanceof Closure) {
            return null;
        }
        return $this->handler[0];
    }


    /**
     * @return string|null
     */
    public function getMethod(): ?string
    {
        if ($this->handler instanceof Closure) {
            return null;
        }
        return $this->handler[1];
    }


    /**
     * @param ServerRequestInterface $request
     * @return ResponseInterface
     * @throws
     */
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $controller = Kiri::getDi()->get($this->handler[0]);

        $data = call_user_func([$controller, $this->handler[1]], ...$this->parameters);

        /** 根据返回类型 */
        return $this->format->call($data);
    }

}
